fidmour support, mouse genericization (the file is now quite misnamed, I'm
authorElliot Lee <sopwith@src.gnome.org>
Mon, 7 Aug 2000 03:31:12 +0000 (03:31 +0000)
committerElliot Lee <sopwith@src.gnome.org>
Mon, 7 Aug 2000 03:31:12 +0000 (03:31 +0000)
fidmour support, mouse genericization (the file is now quite misnamed, I'm afraid).

gdk/linux-fb/gdkinput-ps2.c

index cc4ddb2828d2708f1fa9924f7aa877f44ba00224..451dfb094a98862ad346da2d8bf7c68aa7b71dcc 100644 (file)
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+
 /*
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
@@ -48,7 +49,10 @@ typedef struct {
   GdkWindow *prev_window;
   gboolean button1_pressed, button2_pressed, button3_pressed;
   gboolean click_grab;
-} PS2Mouse;
+
+  guchar fidmour_bytes[5];
+  int fidmour_nbytes;
+} MouseDevice;
 
 typedef struct {
   gint fd, fd_tag, consfd;
@@ -62,9 +66,8 @@ typedef struct {
 static Keyboard * tty_keyboard_open(void);
 static guint keyboard_get_state(Keyboard *k);
 
-PS2Mouse *gdk_fb_ps2mouse = NULL;
+static MouseDevice *gdk_fb_mouse = NULL;
 static Keyboard *keyboard = NULL;
-FILE *debug_out;
 
 static guint multiclick_tag;
 static GdkEvent *multiclick_event = NULL;
@@ -92,7 +95,7 @@ click_event_timeout(gpointer x)
 }
 
 static void
-send_button_event(PS2Mouse *mouse, guint button, gboolean press_event, time_t the_time)
+send_button_event(MouseDevice *mouse, guint button, gboolean press_event, time_t the_time)
 {
   GdkEvent *event;
   gint x, y;
@@ -354,7 +357,7 @@ gdk_fb_get_cursor_rect(GdkRectangle *rect)
 }
 
 static void
-move_pointer(PS2Mouse *mouse, GdkWindow *in_window)
+move_pointer(MouseDevice *mouse, GdkWindow *in_window)
 {
   GdkCursor *the_cursor;
 
@@ -396,7 +399,7 @@ gdk_fb_cursor_reset(void)
 {
   GdkWindow *win = gdk_window_get_pointer(NULL, NULL, NULL, NULL);
 
-  move_pointer(gdk_fb_ps2mouse, win);
+  move_pointer(gdk_fb_mouse, win);
 }
 
 void gdk_fb_window_visibility_crossing(GdkWindow *window, gboolean is_show, gboolean is_grab)
@@ -471,22 +474,227 @@ void gdk_fb_window_visibility_crossing(GdkWindow *window, gboolean is_show, gboo
          event->crossing.state = my_mask;
        }
 
-      if(gdk_fb_ps2mouse->prev_window)
-       gdk_window_unref(gdk_fb_ps2mouse->prev_window);
-      gdk_fb_ps2mouse->prev_window = gdk_window_ref(newwin);
+      if(gdk_fb_mouse->prev_window)
+       gdk_window_unref(gdk_fb_mouse->prev_window);
+      gdk_fb_mouse->prev_window = gdk_window_ref(newwin);
+    }
+}
+
+static void
+handle_mouse_input(MouseDevice *mouse, gboolean got_motion)
+{
+  GdkWindow *mousewin;
+  GdkEvent *event;
+  gint x, y;
+  GdkWindow *win;
+  guint state;
+
+  if(_gdk_fb_pointer_grab_confine)
+    mousewin = _gdk_fb_pointer_grab_confine;
+  else
+    mousewin = gdk_parent_root;
+
+  if(mouse->x < GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_x)
+    mouse->x = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_x;
+  else if(mouse->x > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1))
+    mouse->x = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1;
+  if(mouse->y < GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_y)
+    mouse->y = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_y;
+  else if(mouse->y > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1))
+    mouse->y = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1;
+
+  if(!got_motion)
+    return;
+
+  win = gdk_window_get_pointer(NULL, NULL, NULL, NULL);
+  move_pointer(mouse, win);
+  if(_gdk_fb_pointer_grab_window_events)
+    win = _gdk_fb_pointer_grab_window_events;
+
+  gdk_window_get_origin(win, &x, &y);
+  x = mouse->x - x;
+  y = mouse->y - y;
+
+
+  state = (mouse->button1_pressed?GDK_BUTTON1_MASK:0)
+    | (mouse->button2_pressed?GDK_BUTTON2_MASK:0)
+    | (mouse->button3_pressed?GDK_BUTTON3_MASK:0)
+    | keyboard_get_state(keyboard);
+
+  event = gdk_event_make (win, GDK_MOTION_NOTIFY, TRUE);
+  if(event)
+    {
+      event->motion.x = x;
+      event->motion.y = y;
+      event->motion.state = state;
+      event->motion.is_hint = FALSE;
+      event->motion.device = gdk_core_pointer;
+      event->motion.x_root = mouse->x;
+      event->motion.y_root = mouse->y;
+    }
+
+  if(win != mouse->prev_window)
+    {
+      GdkEvent *evel;
+
+      if(mouse->prev_window && (evel = gdk_event_make(mouse->prev_window, GDK_LEAVE_NOTIFY, TRUE)))
+       {
+         evel->crossing.subwindow = gdk_window_ref(win);
+         evel->crossing.x = x;
+         evel->crossing.y = y;
+         evel->crossing.x_root = mouse->x;
+         evel->crossing.y_root = mouse->y;
+         evel->crossing.mode = GDK_CROSSING_NORMAL;
+         evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
+         evel->crossing.focus = FALSE;
+         evel->crossing.state = state;
+       }
+
+      evel = gdk_event_make(win, GDK_ENTER_NOTIFY, TRUE);
+      if(evel)
+       {
+         evel->crossing.subwindow = gdk_window_ref(mouse->prev_window?mouse->prev_window:gdk_parent_root);
+         evel->crossing.x = x;
+         evel->crossing.y = y;
+         evel->crossing.x_root = mouse->x;
+         evel->crossing.y_root = mouse->y;
+         evel->crossing.mode = GDK_CROSSING_NORMAL;
+         evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
+         evel->crossing.focus = FALSE;
+         evel->crossing.state = state;
+       }
+
+      if(mouse->prev_window)
+       gdk_window_unref(mouse->prev_window);
+      mouse->prev_window = gdk_window_ref(win);
+    }
+}
+
+static gboolean
+pull_fidmour_packet(MouseDevice *mouse, gboolean *btn_down, int *x, int *y)
+{
+  gboolean keep_reading = TRUE;
+
+  while(keep_reading)
+    {
+      int n;
+
+      n = read(mouse->fd, mouse->fidmour_bytes + mouse->fidmour_nbytes, 5 - mouse->fidmour_nbytes);
+      if(n < 0)
+       return FALSE;
+      else if(n == 0)
+       {
+         g_error("EOF on mouse device!");
+         g_source_remove(mouse->fd_tag);
+         return FALSE;
+       }
+
+      mouse->fidmour_nbytes += n;
+
+      n = 0;
+      if(!(mouse->fidmour_bytes[0] & 0x80))
+       {
+         int i;
+         /* We haven't received any of the packet yet but there is no header at the beginning */
+         for(i = 1; i < mouse->fidmour_nbytes; i++)
+           {
+             if(mouse->fidmour_bytes[i] & 0x80)
+               {
+                 n = i;
+                 break;
+               }
+           }
+       }
+      else if(mouse->fidmour_nbytes > 1
+             && ((mouse->fidmour_bytes[0] & 0x90) == 0x90))
+       {
+         /* eat the 0x90 and following byte, no clue what it's for */
+         n = 2;
+       }
+      else if(mouse->fidmour_nbytes == 5)
+       {
+         switch(mouse->fidmour_bytes[0] & 0x80)
+           {
+           case 2:
+             *btn_down = 0;
+             break;
+           case 1:
+           case 0:
+             *btn_down = 1;
+             break;
+           }
+         *x = (mouse->fidmour_bytes[1] << 1) + (mouse->fidmour_bytes[2] << 7);
+         *y = (mouse->fidmour_bytes[3] << 1) + (mouse->fidmour_bytes[4] << 7);
+         n = 5;
+         keep_reading = FALSE;
+       }
+
+      if(n)
+       {
+         memmove(mouse->fidmour_bytes, mouse->fidmour_bytes+n, mouse->fidmour_nbytes-n);
+         mouse->fidmour_nbytes -= n;
+       }
     }
+
+  return TRUE;
 }
 
 static gboolean
-handle_input(GIOChannel *gioc, GIOCondition cond, gpointer data)
+handle_input_fidmour(GIOChannel *gioc, GIOCondition cond, gpointer data)
 {
+  MouseDevice *mouse = data;
+  int x, y;
+  gboolean got_motion = FALSE;
+  gboolean btn_down;
+  time_t the_time;
+  GTimeVal tv;
+
+  g_get_current_time(&tv);
+  the_time = tv.tv_sec;
+
+  while(pull_fidmour_packet(mouse, &btn_down, &x, &y))
+    {
+#if 0
+      if(x != mouse->x
+        || y != mouse->y)
+       got_motion = TRUE;
+      mouse->x = x;
+      mouse->y = y;
+#else
+      g_print("%d at %dx%d\n",
+             btn_down, x, y);
+      continue;
+#endif
+      
+
+      if(btn_down != mouse->button1_pressed)
+       {
+         if(got_motion)
+           {
+             handle_mouse_input(mouse, TRUE);
+             got_motion = FALSE;
+           }
+
+         mouse->button1_pressed = btn_down;
+         send_button_event(mouse, 1, btn_down, the_time);
+       }
+    }
+
+  if(got_motion)
+    handle_mouse_input(mouse, TRUE);
+
+  return TRUE;
+}
+
+static gboolean
+handle_input_ps2(GIOChannel *gioc, GIOCondition cond, gpointer data)
+{
+  MouseDevice *mouse = data;
   guchar buf[3];
   int n, left, dx=0, dy=0;
-  PS2Mouse *mouse = data;
   gboolean new_button1, new_button2, new_button3;
   time_t the_time;
   GTimeVal curtime;
-  GdkWindow *mousewin;
   gboolean got_motion = FALSE;
 
   g_get_current_time(&curtime);
@@ -513,6 +721,17 @@ handle_input(GIOChannel *gioc, GIOCondition cond, gpointer data)
       new_button3 = (buf[0] & 2) && 1;
       new_button2 = (buf[0] & 4) && 1;
 
+      if(got_motion &&
+        (new_button1 != mouse->button1_pressed
+         || new_button2 != mouse->button2_pressed
+         || new_button3 != mouse->button3_pressed))
+       {
+         /* If a mouse button state changes we need to get correct ordering with enter/leave events,
+            so push those out via handle_mouse_input */
+         got_motion = FALSE;
+         handle_mouse_input(mouse, TRUE);
+       }
+
       if(new_button1 != mouse->button1_pressed)
        {
          mouse->button1_pressed = new_button1; 
@@ -545,136 +764,105 @@ handle_input(GIOChannel *gioc, GIOCondition cond, gpointer data)
       if(dx || dy)
        got_motion = TRUE;
     }
- done_reading_mouse_events:
-
-  if(_gdk_fb_pointer_grab_confine)
-    mousewin = _gdk_fb_pointer_grab_confine;
-  else
-    mousewin = gdk_parent_root;
-
-  if(mouse->x < 0)
-    mouse->x = 0;
-  else if(mouse->x > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1))
-    mouse->x = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1;
-  if(mouse->y < 0)
-    mouse->y = 0;
-  else if(mouse->y > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1))
-    mouse->y = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1;
 
-  if(got_motion) {
-    GdkEvent *event;
-    gint x, y;
-    GdkWindow *win;
-    guint state;
-
-    win = gdk_window_get_pointer(NULL, NULL, NULL, NULL);
-    move_pointer(mouse, win);
-    if(_gdk_fb_pointer_grab_window_events)
-      win = _gdk_fb_pointer_grab_window_events;
-
-    gdk_window_get_origin(win, &x, &y);
-    x = mouse->x - x;
-    y = mouse->y - y;
-
-
-    state = (mouse->button1_pressed?GDK_BUTTON1_MASK:0)
-      | (mouse->button2_pressed?GDK_BUTTON2_MASK:0)
-      | (mouse->button3_pressed?GDK_BUTTON3_MASK:0)
-      | keyboard_get_state(keyboard);
-
-    event = gdk_event_make (win, GDK_MOTION_NOTIFY, TRUE);
-    if(event)
-      {
-       event->motion.x = x;
-       event->motion.y = y;
-       event->motion.state = state;
-       event->motion.is_hint = FALSE;
-       event->motion.device = gdk_core_pointer;
-       event->motion.x_root = mouse->x;
-       event->motion.y_root = mouse->y;
-      }
-
-    if(win != mouse->prev_window)
-      {
-       GdkEvent *evel;
-
-       if(mouse->prev_window && (evel = gdk_event_make(mouse->prev_window, GDK_LEAVE_NOTIFY, TRUE)))
-         {
-           evel->crossing.subwindow = gdk_window_ref(win);
-           evel->crossing.x = x;
-           evel->crossing.y = y;
-           evel->crossing.x_root = mouse->x;
-           evel->crossing.y_root = mouse->y;
-           evel->crossing.mode = GDK_CROSSING_NORMAL;
-           evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
-           evel->crossing.focus = FALSE;
-           evel->crossing.state = state;
-         }
-
-       evel = gdk_event_make(win, GDK_ENTER_NOTIFY, TRUE);
-       if(evel)
-         {
-           evel->crossing.subwindow = gdk_window_ref(mouse->prev_window?mouse->prev_window:gdk_parent_root);
-           evel->crossing.x = x;
-           evel->crossing.y = y;
-           evel->crossing.x_root = mouse->x;
-           evel->crossing.y_root = mouse->y;
-           evel->crossing.mode = GDK_CROSSING_NORMAL;
-           evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
-           evel->crossing.focus = FALSE;
-           evel->crossing.state = state;
-         }
-
-       if(mouse->prev_window)
-         gdk_window_unref(mouse->prev_window);
-       mouse->prev_window = gdk_window_ref(win);
-      }
-  }
+ done_reading_mouse_events:
+  if(got_motion)
+    handle_mouse_input(mouse, TRUE);
 
   return TRUE;
 }
 
-static PS2Mouse *
+static MouseDevice *
 mouse_open(void)
 {
-  PS2Mouse *retval = g_new0(PS2Mouse, 1);
+  MouseDevice *retval = g_new0(MouseDevice, 1);
   guchar buf[7];
   int i = 0;
   GIOChannel *gioc;
-
-  retval->fd = open("/dev/psaux", O_RDWR);
-  if(retval->fd < 0)
+  char *mousedev, *ctmp;
+  int mode;
+  enum { PS2_MOUSE, FIDMOUR_MOUSE, UNKNOWN_MOUSE } type;
+
+  retval->fd = -1;
+  mode = O_RDWR;
+  ctmp = getenv("GDK_MOUSETYPE");
+  if(ctmp)
     {
-      g_free(retval);
-      return NULL;
+      if(!strcmp(ctmp, "fidmour"))
+       type = FIDMOUR_MOUSE;
+      else if(!strcmp(ctmp, "ps2"))
+       type = PS2_MOUSE;
+      else
+       {
+         g_print("Unknown mouse type %s\n", ctmp);
+         type = UNKNOWN_MOUSE;
+       }
     }
+  else
+    type = PS2_MOUSE;
 
-  /* From xf86_Mouse.c */
-  buf[i++] = 230; /* 1:1 scaling */
-  buf[i++] = 244; /* enable mouse */
-  buf[i++] = 243; /* Sample rate */
-  buf[i++] = 200;
-  buf[i++] = 232; /* device resolution */
-  buf[i++] = 1;
-  write(retval->fd, buf, i);
-  if(read(retval->fd, buf, 3) < 0
-     || getenv("GDK_NO_PS2MOUSE")) /* Get rid of misc garbage whatever stuff from mouse */
+  switch(type)
     {
-      close(retval->fd);
-      retval->fd = -1;
+    case PS2_MOUSE:
+      mousedev = "/dev/psaux";
+      mode = O_RDWR;
+      break;
+    case FIDMOUR_MOUSE:
+      mousedev = "/dev/fidmour";
+      mode = O_RDONLY;
+      break;
+    default:
+      goto error;
+      break;
     }
-  else
+
+  ctmp = getenv("GDK_MOUSEDEV");
+  if(ctmp)
+    mousedev = ctmp;
+
+  retval->fd = open(mousedev, mode);
+  if(retval->fd < 0)
+    goto error;
+
+  switch(type)
     {
+    case PS2_MOUSE:
+      /* From xf86_Mouse.c */
+      buf[i++] = 230; /* 1:1 scaling */
+      buf[i++] = 244; /* enable mouse */
+      buf[i++] = 243; /* Sample rate */
+      buf[i++] = 200;
+      buf[i++] = 232; /* device resolution */
+      buf[i++] = 1;
+      write(retval->fd, buf, i);
+      if(read(retval->fd, buf, 3) < 0)
+       goto error;
       fcntl(retval->fd, F_SETFL, O_RDWR|O_NONBLOCK);
 
       gioc = g_io_channel_unix_new(retval->fd);
-      retval->fd_tag = g_io_add_watch(gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input, retval);
+      retval->fd_tag = g_io_add_watch(gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input_ps2, retval);
+      break;
+
+    case FIDMOUR_MOUSE:
+      gioc = g_io_channel_unix_new(retval->fd);
+      retval->fd_tag = g_io_add_watch(gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input_fidmour, retval);
+      break;
+    default:
+      g_assert_not_reached();
+      break;
     }
 
   retval->x = gdk_display->modeinfo.xres >> 1;
   retval->y = gdk_display->modeinfo.yres >> 1;
 
   return retval;
+
+ error:
+  /* No errors allowed once fd_tag is added */
+  if(retval->fd >= 0)
+    close(retval->fd);
+  g_free(retval);
+  return NULL;
 }
 
 void
@@ -684,18 +872,18 @@ gdk_input_init (void)
 
   gdk_input_ignore_core = FALSE;
 
-  gdk_fb_ps2mouse = mouse_open();
+  gdk_fb_mouse = mouse_open();
 }
 
 void
 gdk_input_ps2_get_mouseinfo(gint *x, gint *y, GdkModifierType *mask)
 {
-  *x = gdk_fb_ps2mouse->x;
-  *y = gdk_fb_ps2mouse->y;
+  *x = gdk_fb_mouse->x;
+  *y = gdk_fb_mouse->y;
   *mask =
-    (gdk_fb_ps2mouse->button1_pressed?GDK_BUTTON1_MASK:0)
-    | (gdk_fb_ps2mouse->button2_pressed?GDK_BUTTON2_MASK:0)
-    | (gdk_fb_ps2mouse->button3_pressed?GDK_BUTTON3_MASK:0)
+    (gdk_fb_mouse->button1_pressed?GDK_BUTTON1_MASK:0)
+    | (gdk_fb_mouse->button2_pressed?GDK_BUTTON2_MASK:0)
+    | (gdk_fb_mouse->button3_pressed?GDK_BUTTON3_MASK:0)
     | keyboard_get_state(keyboard);
 }
 
@@ -1120,8 +1308,6 @@ handle_keyboard_input(GIOChannel *gioc, GIOCondition cond, gpointer data)
            {
              gint vtnum = trans_table[base_char][0] - GDK_F1 + 1;
 
-             fprintf(debug_out, "Switching VTs\n");
-
              /* Do the whole funky VT switch thing */
              ioctl(k->consfd, VT_ACTIVATE, vtnum);
              ioctl(k->consfd, VT_WAITACTIVE, k->vtnum);
@@ -1208,8 +1394,6 @@ tty_keyboard_open(void)
   ioctl(retval->consfd, VT_ACTIVATE, retval->vtnum);
   ioctl(retval->consfd, VT_WAITACTIVE, retval->vtnum);
 
-  debug_out = fdopen(dup(2), "w");
-
 #if 0
   close(0);
   close(1);